[LINUX] Kexec: Ensure that pages allocated for kexec have MFNs which are within
authorIan Campbell <ian.campbell@xensource.com>
Wed, 14 Mar 2007 16:39:32 +0000 (16:39 +0000)
committerIan Campbell <ian.campbell@xensource.com>
Wed, 14 Mar 2007 16:39:32 +0000 (16:39 +0000)
the required limits.

Previously we were lucky since most dom0 pages would be low enough but now Xen
is more aggressive in giving out higher MFNs when it can.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
linux-2.6-xen-sparse/kernel/kexec.c

index c46558f7dabbc978bb0178c6910ea4358eb02493..a6e212013809f4d798a3b8809d83e2de39e69405 100644 (file)
@@ -330,13 +330,27 @@ static int kimage_is_destination_range(struct kimage *image,
        return 0;
 }
 
-static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
+static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order, unsigned long limit)
 {
        struct page *pages;
 
        pages = alloc_pages(gfp_mask, order);
        if (pages) {
                unsigned int count, i;
+#ifdef CONFIG_XEN
+               int address_bits;
+
+               if (limit == ~0UL)
+                       address_bits = BITS_PER_LONG;
+               else
+                       address_bits = long_log2(limit);
+
+               if (xen_create_contiguous_region((unsigned long)page_address(pages),
+                                                order, address_bits) < 0) {
+                       __free_pages(pages, order);
+                       return NULL;
+               }
+#endif
                pages->mapping = NULL;
                set_page_private(pages, order);
                count = 1 << order;
@@ -355,6 +369,9 @@ static void kimage_free_pages(struct page *page)
        count = 1 << order;
        for (i = 0; i < count; i++)
                ClearPageReserved(page + i);
+#ifdef CONFIG_XEN
+       xen_destroy_contiguous_region((unsigned long)page_address(page), order);
+#endif
        __free_pages(page, order);
 }
 
@@ -400,7 +417,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
        do {
                unsigned long pfn, epfn, addr, eaddr;
 
-               pages = kimage_alloc_pages(GFP_KERNEL, order);
+               pages = kimage_alloc_pages(GFP_KERNEL, order, KEXEC_CONTROL_MEMORY_LIMIT);
                if (!pages)
                        break;
                pfn   = kexec_page_to_pfn(pages);
@@ -709,7 +726,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
                kimage_entry_t *old;
 
                /* Allocate a page, if we run out of memory give up */
-               page = kimage_alloc_pages(gfp_mask, 0);
+               page = kimage_alloc_pages(gfp_mask, 0, KEXEC_SOURCE_MEMORY_LIMIT);
                if (!page)
                        return NULL;
                /* If the page cannot be used file it away */